<template>
  <div class="container">
    <div class="toolbar">
      <n-space>
        <n-button type="primary" @click="add">添加</n-button>
        <n-button @click="reload">刷新</n-button>
      </n-space>
      <n-space justify="end" class="search">
        <n-input-group style="width: 450px">
          <n-select v-model:value="searchForm.type" :style="{ width: '150px' }" :options="[
            { label: '账号', value: 0 },
            { label: '密码', value: 1 },
            { label: '是否已认证', value: 2 },
            { label: '执行天数', value: 3 },
            { label: '每天执行观看次数', value: 4 },
          ]" />

          <n-input v-if="[0, 1].includes(searchForm.type)"
            v-model:value="searchForm.keyword"
            clearable
            :style="{ width: '250px' }"
          />
          <n-select v-else-if="[2].includes(searchForm.type)"
            v-model:value="searchForm.keyword"
            clearable
            :style="{ width: '250px' }"
            :options="[
              { label: '是', value: 1 },
              { label: '否', value: 0 },
            ]"
          />
          <n-input-number v-else-if="[3, 4].includes(searchForm.type)"
            v-model:value="searchForm.keyword"
            clearable
            :style="{ width: '250px' }"
          />

          <n-button
            type="primary"
            ghost
            :style="{ width: '50px' }"
            @click="search"
          >
            搜索
          </n-button>
        </n-input-group>
      </n-space>
    </div>
    <n-data-table
      size="small"
      :columns="columns"
      :data="data"
      :pagination="pagination"
      :scroll-x="625"
      :loading="fetching"
      :remote="true"
      :row-key="row => row.id"
      striped
    />
  </div>

  <n-modal v-model:show="showAddPanel" mask-closable>
    <n-card
      style="width: 600px"
      title="添加账号"
      size="huge"
      :bordered="false"
      role="dialog"
      aria-modal="true"
    >
      <n-form ref="addFormRef" :model="addModel" :rules="addRules">
        <n-form-item path="username" label="账号">
          <n-input v-model:value="addModel.username" @keydown.enter.prevent />
        </n-form-item>
        <n-form-item path="password" label="密码">
          <n-input v-model:value="addModel.password" @keydown.enter.prevent />
        </n-form-item>
        <n-form-item path="is_identity" label="是否实名">
          <n-select
            :options="[
              {
                label: '是',
                value: true
              },
              {
                label: '否',
                value: false
              }
            ]"
            v-model:value="addModel.is_identity"
            @keydown.enter.prevent
          />
        </n-form-item>
        <n-form-item path="exec_date" label="脚本执行天数">
          <n-input-number v-model:value="addModel.exec_date" @keydown.enter.prevent />
        </n-form-item>
        <n-form-item path="exec_times_per_day" label="每天脚本执行观看广告次数">
          <n-input-number v-model:value="addModel.exec_times_per_day" @keydown.enter.prevent />
        </n-form-item>
      </n-form>
      <n-space justify="start">
          <n-button round
            type="primary"
            @click="handleAddAccount"
            :loading="addRequesting"
            :disabled="addRequesting"
          >
            添加账号
          </n-button>
      </n-space>
    </n-card>
  </n-modal>
</template>

<script setup>
import { ref, reactive, defineComponent, h, nextTick } from "vue"
import { useRequests } from "@/common/requests.js"
import {
  NSpace,
  NInput,
  NButton,
  NLayout,
  NLayoutContent,
  NDataTable,
  useMessage,
  useNotification,
  NInputNumber, NSelect
} from "naive-ui";
import { request } from "@/common/http.js";

const message = useMessage()
const notify = useNotification()
const requests = useRequests()

const ShowOrEdit = defineComponent({
  props: {
    value: [String, Number, Boolean],
    type: String,
    render: Function,
    onUpdateValue: [Function, Array]
  },
  setup (props) {
    const isEdit = ref(false)
    const inputRef = ref(null)
    const inputValue = ref(props.value)
    const loading = ref(false)

    const handleOnClick = () => {
      isEdit.value = true
      nextTick(() => {
        console.log(inputRef.value)
        inputRef.value.focus()
      })
    }

    const handleChange = () => {
      if (inputValue.value != props.value) {
        props.onUpdateValue(inputValue.value, loading)
      }

      isEdit.value = false
    }

    const typeInput = {
      default: {
        el: NInput,
        options: {}
      },
      number: {
        el: NInputNumber,
        options: {}
      },
      yesOrNot: {
        el: NSelect,
        options: {
          options: [
            {
              label: "是",
              value: true
            },
            {
              label: "否",
              value: false
            },
          ]
        }
      },
    }

    return () =>
      h('div', {
          onClick: handleOnClick
        },
        isEdit.value
          ? h(typeInput[props.type ?? 'default'].el, {
            ...{
              ref: inputRef,
              value: inputValue.value,
              onUpdateValue: (v) => {
                inputValue.value = v
                handleChange
              },
              onBlur: handleChange
            },
            ...typeInput[props.type ?? 'default'].options
          })
          : (props.render ? props.render(props.value) : props.value)
      )
  }
})
const columns = [
  {
    title: '#',
    key: 'id',
    width: '150'
  },
  {
    title: '账号',
    key: 'username',
    render: (row, index) => {
      return h(ShowOrEdit, {
        value: row.username,
        onUpdateValue (v, loading) {
          update({id: row.id, username: v},
            () => data.value[index].username = v)
        }
      })
    }
  },
  {
    title: '密码',
    key: 'password',
    render: (row, index) => {
      return h(ShowOrEdit, {
        value: row.password,
        onUpdateValue (v, loading) {
          update({id: row.id, password: v},
            () => data.value[index].password = v)
        }
      })
    }
  },
  {
    title: '是否实名',
    key: 'is_identity',
    render: (row, index) => {
      return h(ShowOrEdit, {
        type: 'yesOrNot',
        render: val => val ? '是' : '否',
        value: row.is_identity,
        onUpdateValue (v, loading) {
          update({id: row.id, is_identity: v},
            () => data.value[index].is_identity = v)
        }
      })
    }
  },
  {
    title: '执行天数',
    key: 'exec_date',
    render: (row, index) => {
      return h(ShowOrEdit, {
        type: 'number',
        value: row.exec_date,
        onUpdateValue (v, loading) {
          update({id: row.id, exec_date: v},
            () => data.value[index].exec_date = v)
        }
      })
    }
  },
  {
    title: '每天执行次数',
    key: 'exec_times_per_day',
    render: (row, index) => {
      return h(ShowOrEdit, {
        type: 'number',
        value: row.exec_times_per_day,
        onUpdateValue (v, loading) {
          update({id: row.id, exec_times_per_day: v},
            () => data.value[index].exec_times_per_day = v)
        }
      })
    }
  },
  {
    title: '操作',
    key: 'action',
    width: 80,
    fixed: 'right',
    render(row) {
      return h(NSpace, {justify: 'center'}, {
        default: () => [
          h(NButton, {
            size: 'small',
            type: 'error',
            loading: row.requesting,
            disabled: row.requesting,
            onClick: () => deleteAccount(row)
          }, {
            default: () => '删除'
          }),
        ]
      });
    }
  }
]

const data = ref([])
const pagination = reactive({
  page: 1,
  pageSize: 10,
  showSizePicker: true,
  pageSizes: [10, 15, 20, 50],
  itemCount: 0,
  pageCount: 1,
  onChange: (page) => {
    pagination.page = page
    fetch()
  },
  onUpdatePageSize: (pageSize) => {
    pagination.pageSize = pageSize
    pagination.page = 1

    fetch()
  }
})

const fetching = ref(false)
const fetch = () => {
  fetching.value = true
  let request,
    params = { page: pagination.page, offset: pagination.pageSize };
  if (searchForm.value.keyword !== null && String(searchForm.value.keyword).length > 0) {
    request = requests.account.search
    params = {...params, ...searchForm.value}
  } else {
    request = requests.account.list
  }

  request(params).then(resp => {
    fetching.value = false
    if (resp.ret === 0) {
      data.value = resp.data.list

      pagination.itemCount = resp.data.total
      pagination.pageCount = Math.ceil(resp.data.total / pagination.pageSize)
    } else {
      message.error(resp?.data ?? resp?.msg ?? '未知错误')
    }
  }).catch(err => {
    fetching.value = false

    console.log(err)
    notify.error({content: "出错了", meta: err.toString(), duration: 3000})
  })
}

const update = (data, cb) => {
  requests.account.update(data).then(resp => {
    if (resp.ret === 0) {
      message.success('修改成功')
      cb()
    } else {
      message.error(resp?.data ?? resp?.msg ?? '未知错误')
    }
  }).catch(err => {
    fetching.value = false

    console.log(err)
    notify.error({content: "出错了", meta: err.toString(), duration: 3000})
  })
}

const reload = () => {
  pagination.page = 1
  fetch()
}

const deleteAccount = row => {
  row.requesting = true
  requests.account.delete(row.id).then(resp => {
    row.requesting = false
    if (resp.ret === 0) {
      fetch()
      message.success("删除成功")
    } else {
      message.error(resp?.data ?? resp?.msg ?? '未知错误')
    }
  }).catch(err => {
    row.requesting = false

    console.log(err)
    notify.error({content: "出错了", meta: err.toString(), duration: 3000})
  })
}

const showAddPanel = ref(false)
const addFormRef = ref(null)
const addRequesting = ref(false)
const addModel = ref({
  username: null,
  password: null,
  is_identity: null,
  exec_date: null,
  exec_times_per_day: null
})
const addRules = ref({
  username: {
    required: true,
    message: '请输入账号',
    trigger: ['blur', 'input']
  },
  password: {
    required: true,
    message: '请输入账号',
    trigger: ['blur', 'input']
  },
  is_identity: {
    type: 'boolean',
    required: true,
    message: '请选择是否已实名',
    trigger: ['blur', 'change']
  },
  exec_date: {
    type: 'number',
    required: true,
    message: '请输入执行天数',
    trigger: ['blur', 'change']
  },
  exec_times_per_day: {
    type: 'number',
    required: true,
    message: '请输入每天执行观看次数',
    trigger: ['blur', 'change']
  }
})
const add = () => {
  showAddPanel.value = true
}
const handleAddAccount = () => {
  addFormRef.value?.validate((errors) => {
    if (!errors) {
      addRequesting.value = true
      requests.account.add(addModel.value).then(resp => {
        addRequesting.value = false
        if (resp.ret === 0) {
          showAddPanel.value = false
          message.success('添加成功')
        } else {
          message.error(resp?.data ?? resp?.msg ?? '未知错误')
        }
      }).catch(err => {
        addRequesting.value = false

        console.log(err)
        notify.error({content: "出错了", meta: err.toString(), duration: 3000})
      })
    }
  })
}

const searchForm = ref({
  type: 0,
  keyword: null
})

const search = () => {
  pagination.page = 1
  fetch()
}

fetch()
</script>

<style lang="scss" scoped>
.container {
  padding: 2rem;

  .toolbar {
    margin-bottom: 1rem;
    display: flex;

    .search {
      flex: 1;
    }
  }
}
</style>
